package com.gitee.empty_null.authorization.converter;

import com.gitee.empty_null.authorization.authentication.OAuth2UsernamePasswordAuthenticationToken;
import com.gitee.empty_null.authorization.utils.OAuth2EndpointUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * @author xuhainan
 * @date 2024/1/15 16:32
 * @region hefei
 */
public class OAuth2UsernamePasswordAuthenticationConverter implements AuthenticationConverter {

    @SuppressWarnings("deprecation")
    private static final AuthorizationGrantType AUTHORIZATION_GRANT_TYPE = AuthorizationGrantType.PASSWORD;

    @Override
    public Authentication convert(HttpServletRequest request) {
        // grant_type (REQUIRED)
        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
        if (!AUTHORIZATION_GRANT_TYPE.getValue().equals(grantType)) {
            return null;
        }
        Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();

        MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);
        // username (REQUIRED)
        OAuth2EndpointUtils.checkRequiredParameter(parameters, OAuth2ParameterNames.USERNAME);

        // password (REQUIRED)
        OAuth2EndpointUtils.checkRequiredParameter(parameters, OAuth2ParameterNames.PASSWORD);

        // scope (OPTIONAL)
        String scope = OAuth2EndpointUtils.checkOptionalParameter(parameters, OAuth2ParameterNames.SCOPE);

        List<String> scopeList = Arrays.asList(StringUtils.delimitedListToStringArray(scope, " "));

        return new OAuth2UsernamePasswordAuthenticationToken(clientPrincipal,
                new HashSet<>(scopeList),
                new HashMap<>(parameters));
    }

}
